home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsrmt / fsrmtIO.c < prev    next >
C/C++ Source or Header  |  1991-05-04  |  44KB  |  1,399 lines

  1. /* 
  2.  * fsSpriteIO.c --
  3.  *
  4.  *    This has the stubs for remote I/O operations handled by Sprite servers.
  5.  *
  6.  * Copyright (C) 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/fsrmt/RCS/fsrmtIO.c,v 9.15 91/03/30 17:14:19 mgbaker Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include <sprite.h>
  22. #include <fs.h>
  23. #include <fsutil.h>
  24. #include <fsio.h>
  25. #include <fsrmtInt.h>
  26. #include <fsNameOps.h>
  27. #include <fsprefix.h>
  28. #include <fscache.h>
  29. #include <fsconsist.h>
  30. #include <fsutilTrace.h>
  31. #include <fsioFile.h>
  32. #include <fsStat.h>
  33. #include <proc.h>
  34. #include <rpc.h>
  35. #include <vm.h>
  36. #include <dbg.h>
  37. #ifdef SOSP91
  38. #include <sospRecord.h>
  39. #endif /* SOSP91 */
  40.  
  41. int FsrmtRpcCacheUnlockBlock _ARGS_((ClientData clientData));
  42.  
  43. Boolean fsrmt_RpcDebug = FALSE;
  44.  
  45.  
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * Fsrmt_Read --
  50.  *
  51.  *    Read data from a remote file/device/pipe/etc.
  52.  *    This routine is in charge of breaking the request up into pieces
  53.  *    that can be handled by the RPC system.
  54.  *    Also, if the FS_USER flag is present then this will allocate
  55.  *    a temporary buffer in the kernel to avoid addressing problems
  56.  *    in the RPC interrupt handler.
  57.  *
  58.  * Results:
  59.  *    SUCCESS.
  60.  *
  61.  * Side effects:
  62.  *    The buffer is filled with the number of bytes indicated by
  63.  *    the bufSize parameter.  *readCountPtr is filled with the number
  64.  *    of bytes actually read.
  65.  *
  66.  *----------------------------------------------------------------------
  67.  */
  68. ReturnStatus
  69. Fsrmt_Read(streamPtr, readPtr, waitPtr, replyPtr)
  70.     Fs_Stream    *streamPtr;        /* Stream to Remote I/O handle. */
  71.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  72.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  73.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  74.                      * plus the amount read. */
  75. {
  76.     register Fsrmt_IOHandle *rmtHandlePtr =
  77.         (Fsrmt_IOHandle *)streamPtr->ioHandlePtr;
  78.     ReturnStatus     status;
  79.     Rpc_Storage     storage;
  80.     FsrmtIOParam    readParams;
  81.     register Boolean    userSpace;
  82.     int            amountRead;
  83.     register Address    readBufferPtr = (Address)NIL;
  84.  
  85.     status = SUCCESS;
  86.     /*
  87.      * Set up parameters that won't change in each loop iteration.
  88.      */
  89.     readParams.fileID = rmtHandlePtr->hdr.fileID;
  90.     readParams.streamID = streamPtr->hdr.fileID;
  91.     if (waitPtr == (Sync_RemoteWaiter *)NIL) {
  92.     readParams.waiter.hostID = -1;
  93.     readParams.waiter.pid = -1;
  94.     } else {
  95.     readParams.waiter = *waitPtr;
  96.     }
  97.     readParams.io.buffer = 0;    /* not used */
  98.     userSpace = readPtr->flags & FS_USER;
  99.     readParams.io.flags = readPtr->flags & ~FS_USER;
  100.     readParams.io.procID = readPtr->procID;
  101.     readParams.io.familyID = readPtr->familyID;
  102.     readParams.io.uid = readPtr->uid;
  103.     readParams.io.reserved = 0;
  104.  
  105.     storage.requestParamPtr = (Address)&readParams;
  106.     storage.requestParamSize = sizeof(readParams);
  107.     storage.requestDataPtr = (Address)NIL;
  108.     storage.requestDataSize = 0;
  109.  
  110.     /*
  111.      * Allow remote site to return a signal.
  112.      */
  113.     storage.replyParamPtr = (Address)replyPtr;
  114.     storage.replyParamSize = sizeof(Fs_IOReply);
  115.  
  116.     if (userSpace) {
  117.     /*
  118.      * We suffer a malloc and copy cost here because we don't
  119.      * map the users buffer into the kernel and we can't rely
  120.      * on being able to address the user's context from the
  121.      * interrupt handler that receives the packet.
  122.      */
  123.     readBufferPtr =  (Address)malloc((readPtr->length > fsMaxRpcDataSize) ?
  124.                     fsMaxRpcDataSize : readPtr->length);
  125.     }
  126.     /*
  127.      * Outer loop to chop reads into the largest pieces
  128.      * supported by the RPC system.
  129.      */
  130.     amountRead = 0;
  131.     while (readPtr->length > 0) {
  132.     readParams.io.length = (readPtr->length > fsMaxRpcDataSize) ?
  133.                 fsMaxRpcDataSize : readPtr->length;
  134.     readParams.io.offset = readPtr->offset + amountRead;
  135.     if (!userSpace) {
  136.         readBufferPtr = readPtr->buffer + amountRead;
  137.     }
  138.     storage.replyDataSize = readParams.io.length;
  139.     storage.replyDataPtr = readBufferPtr;
  140.  
  141.     status = Rpc_Call(rmtHandlePtr->hdr.fileID.serverID, RPC_FS_READ,
  142.                 &storage);
  143.  
  144.     if (status == SUCCESS || status == FS_WOULD_BLOCK) {
  145.         if (userSpace) {
  146.         if (Vm_CopyOut(storage.replyDataSize, readBufferPtr,
  147.                 readPtr->buffer + amountRead)
  148.                 != SUCCESS) {
  149.             status = FS_INVALID_ARG;
  150.             break;
  151.         }
  152.         }
  153.         readPtr->length -= storage.replyDataSize;
  154.         amountRead += storage.replyDataSize;
  155.         if (storage.replyDataSize < readParams.io.length ||
  156.         status == FS_WOULD_BLOCK) {
  157.         /*
  158.          * Quit on short read because may have hit eof or
  159.          * used up the data in a pipe or device.
  160.          */
  161.         break;
  162.         }
  163.     } else if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  164.         status == RPC_SERVICE_DISABLED) {
  165.         Fsutil_WantRecovery((Fs_HandleHeader *)rmtHandlePtr);
  166.         break;
  167.     } else {
  168.         break;
  169.     }
  170.     }
  171.     replyPtr->length = amountRead;
  172.     Fs_StatAdd(amountRead, fs_Stats.gen.remoteBytesRead,
  173.            fs_Stats.gen.remoteReadOverflow);
  174. #ifdef SOSP91
  175.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  176.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  177.         (proc_RunningProcesses[0]->genFlags &
  178.         (PROC_FOREIGN | PROC_MIGRATING))) {
  179.         Fs_StatAdd(amountRead, fs_SospMigStats.gen.remoteBytesRead, 
  180.             fs_SospMigStats.gen.remoteReadOverflow);
  181.     }
  182.     }
  183. #endif SOSP91
  184.     if (userSpace) {
  185.     free(readBufferPtr);
  186.     }
  187.     return(status);
  188. }
  189.  
  190. /*
  191.  *----------------------------------------------------------------------
  192.  *
  193.  * Fsrmt_RpcRead --
  194.  *
  195.  *    Service stub for the RPC_FS_READ call.  This verifies the client
  196.  *    and uses the stream read routine to get data.
  197.  *    There is also an optimization here to read directly
  198.  *    out of the cache for block-aligned cacheable reads.
  199.  *
  200.  * Results:
  201.  *    A return status.
  202.  *
  203.  * Side effects:
  204.  *      If the read would block (ie, no data ready), the remote caller is
  205.  *      put into the file handle's readWaitList.  If the read went ok
  206.  *    a reply message is returned to the caller.  Note that we may
  207.  *    or may not return an Fs_IOReply.  This is not done with a cache
  208.  *    read because signals are not generated in that case, which is
  209.  *    why the Fs_IOReply struct is used.
  210.  *
  211.  *----------------------------------------------------------------------
  212.  */
  213. /*ARGSUSED*/
  214. ReturnStatus
  215. Fsrmt_RpcRead(srvToken, clientID, command, storagePtr)
  216.     ClientData        srvToken;    /* Handle for the server process */
  217.     int            clientID;    /* Sprite ID of client host */
  218.     int            command;    /* IGNORED */
  219.     register Rpc_Storage *storagePtr;    /* Specifies the size and location of
  220.                      * the two parts of the read request.
  221.                      * This routine sets up parts that
  222.                      * indicate the size and location of
  223.                      * the read reply. */
  224. {
  225.     register FsrmtIOParam    *paramsPtr;
  226.     register Fs_HandleHeader    *hdrPtr;
  227.     register Fs_Stream        *streamPtr;
  228.     ReturnStatus    status;
  229.     Rpc_ReplyMem    *replyMemPtr;    /* For call-back to free buffer */
  230.     int            (*callBack) _ARGS_((ClientData));
  231.                 /* Call back to clean up after RPC */
  232.     ClientData        clientData;    /* Client data for callBack */
  233.  
  234.     callBack = (int(*)()) NIL;
  235.     clientData = (ClientData) NIL;
  236.  
  237.     paramsPtr = (FsrmtIOParam *)storagePtr->requestParamPtr;
  238.  
  239.     /*
  240.      * Fetch the handle for the file and verify the client.
  241.      */
  242.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  243.         (¶msPtr->fileID, clientID, (int *)NIL);
  244.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  245.     printf("Fsrmt_RpcRead, no handle <%d,%d> client %d\n",
  246.         paramsPtr->fileID.major, paramsPtr->fileID.minor, clientID);
  247.     return(FS_STALE_HANDLE);
  248.     }
  249.     Fsutil_HandleUnlock(hdrPtr);
  250.  
  251.     /*
  252.      * Fetch the shadow stream in case we need to use our offset.
  253.      */
  254.     if (paramsPtr->streamID.type == FSIO_STREAM &&
  255.     paramsPtr->streamID.serverID == rpc_SpriteID) {
  256.     streamPtr = Fsio_StreamClientVerify(¶msPtr->streamID, hdrPtr,
  257.             clientID);
  258.     if (streamPtr == (Fs_Stream *)NIL) {
  259.         printf("Fsrmt_RpcRead no stream <%d> to handle <%d,%d> client %d\n",
  260.             paramsPtr->streamID.minor,
  261.             paramsPtr->fileID.major, paramsPtr->fileID.minor,
  262.             clientID);
  263.         Fsutil_HandleRelease(hdrPtr, FALSE);
  264.         return( (paramsPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  265.                             : FS_STALE_HANDLE );
  266.     } else {
  267.         if (paramsPtr->io.flags & FS_RMT_SHARED) {
  268.         paramsPtr->io.offset = streamPtr->offset;
  269.         }
  270.         Fsutil_HandleUnlock(streamPtr);
  271.     }
  272.     } else {
  273.     /*
  274.      * Read from the cache, no stream available.
  275.      */
  276.     streamPtr = (Fs_Stream *)NIL;
  277.     }
  278.  
  279. #ifdef SOSP91
  280.     paramsPtr->io.reserved = clientID;
  281. #endif SOSP91
  282.  
  283.     if (hdrPtr->fileID.type == FSIO_LCL_FILE_STREAM &&
  284.     paramsPtr->io.length == FS_BLOCK_SIZE &&
  285.     (paramsPtr->io.offset & FS_BLOCK_OFFSET_MASK) == 0) {
  286.     /*
  287.      * This is a quick check to see if we can go to the cache
  288.      * directly.  This doesn't fit easily into the
  289.      * Stream read interface so it is left as a wart here instead of
  290.      * permeating the whole interface.
  291.      */
  292.     Fscache_Block    *cacheBlockPtr;    /* Direct reference to cache block */
  293.     Fsio_FileIOHandle *handlePtr = (Fsio_FileIOHandle *)hdrPtr;
  294.     int lengthRead = 0;
  295. #ifdef SOSP91
  296.     Fsconsist_Info *consistPtr = &handlePtr->consist;
  297.     Fsconsist_ClientInfo    *clientPtr;
  298.     int    numReading, numWriting;
  299.  
  300.     LIST_FORALL(&consistPtr->clientList, (List_Links *) clientPtr) {
  301.         if (clientPtr->clientID == clientID) {
  302.             if (!clientPtr->cached) {
  303.             (void) Fsconsist_NumClients(consistPtr, &numReading,
  304.                 &numWriting);
  305.             SOSP_ADD_READ_TRACE(clientID, handlePtr->hdr.fileID,
  306.                 paramsPtr->streamID, TRUE, paramsPtr->io.offset,
  307.                 paramsPtr->io.length, numReading, numWriting);
  308.         }
  309.         break;
  310.         }
  311.     }
  312. #endif SOSP91
  313.  
  314.     status = Fscache_BlockRead(&handlePtr->cacheInfo,
  315.                   paramsPtr->io.offset / FS_BLOCK_SIZE,
  316.                   &cacheBlockPtr, &lengthRead, 
  317.                   FSCACHE_DATA_BLOCK, FALSE);
  318.     if (cacheBlockPtr != (Fscache_Block *)NIL) {
  319.         storagePtr->replyDataPtr = cacheBlockPtr->blockAddr;
  320.         storagePtr->replyDataSize = lengthRead;
  321.         callBack = FsrmtRpcCacheUnlockBlock;
  322.         clientData = (ClientData)cacheBlockPtr;
  323.     } else {
  324.         /*
  325.          * Either we are past eof or there was an I/O error.
  326.          * No data to return.
  327.          */
  328.         callBack = (int(*)())NIL;
  329.         clientData = (ClientData)NIL;
  330.     }
  331.     if (streamPtr != (Fs_Stream *)NIL) {
  332.         streamPtr->offset = paramsPtr->io.offset + lengthRead;
  333.         Fsutil_HandleLock(streamPtr);
  334.         Fsutil_HandleRelease(streamPtr, TRUE);
  335.     }
  336.     } else {
  337.     /*
  338.      * Regular read to a file, device, pipe, pseudo-device.
  339.      */
  340.     Fs_IOReply *replyPtr = mnew(Fs_IOReply);
  341.  
  342.     replyPtr->length = 0;
  343.     replyPtr->signal = 0;
  344.     replyPtr->flags = 0;
  345.     paramsPtr->io.buffer = (Address) malloc(paramsPtr->io.length);
  346.  
  347.     if (streamPtr == (Fs_Stream *)NIL) {
  348.         printf("Fsrmt_RpcRead, non block-aligned cache read from client %d\n",
  349.         clientID);
  350.         status = GEN_INVALID_ARG;
  351.     } else {
  352.         status = (fsio_StreamOpTable[hdrPtr->fileID.type].read)(streamPtr,
  353.                 ¶msPtr->io, ¶msPtr->waiter, replyPtr);
  354.         streamPtr->offset = paramsPtr->io.offset + replyPtr->length;
  355.         Fsutil_HandleLock(streamPtr);
  356.         Fsutil_HandleRelease(streamPtr, TRUE);
  357.     }
  358.  
  359.     if (status == SUCCESS || status == FS_WOULD_BLOCK) {
  360.         storagePtr->replyDataPtr = paramsPtr->io.buffer;
  361.         storagePtr->replyDataSize = replyPtr->length;
  362.         storagePtr->replyParamPtr = (Address)replyPtr;
  363.         storagePtr->replyParamSize = sizeof(Fs_IOReply);
  364.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  365.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  366.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  367.         callBack = Rpc_FreeMem;
  368.         clientData = (ClientData)replyMemPtr;
  369.     } else {
  370.         free(paramsPtr->io.buffer);
  371.         free((Address)replyPtr);
  372.     }
  373.     }
  374.     Fsutil_HandleRelease(hdrPtr, FALSE);
  375.     FSRMT_RPC_DEBUG_PRINT1("Fsrmt_RpcRead: Returning %x\n", status);
  376.     if (status == SUCCESS || status == FS_WOULD_BLOCK) {
  377.     Rpc_Reply(srvToken, status, storagePtr, callBack, clientData);
  378.     return(SUCCESS);
  379.     } else {
  380.     return(status);
  381.     }
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * FsrmtRpcCacheUnlockBlock --
  388.  *
  389.  *    A call-back to release a cache block after a successful read RPC.
  390.  *
  391.  * Results:
  392.  *    None.
  393.  *
  394.  * Side effects:
  395.  *    Unlock the cache block locked down during a read for a remote client.
  396.  *
  397.  *----------------------------------------------------------------------
  398.  */
  399. int
  400. FsrmtRpcCacheUnlockBlock(clientData)
  401.     ClientData clientData;
  402. {
  403.     Fscache_Block *cacheBlockPtr = (Fscache_Block *) clientData;
  404.     Fscache_UnlockBlock(cacheBlockPtr, 0, -1, 0, FSCACHE_CLEAR_READ_AHEAD);
  405.     return 0;
  406. }
  407.  
  408.  
  409.  
  410. /*----------------------------------------------------------------------
  411.  *
  412.  * Fsrmt_Write --
  413.  *
  414.  *      Write to a remote Sprite file, device, or pipe.  This is in charge
  415.  *    of breaking the write up into pieces that the RPC system can handle.
  416.  *
  417.  * Results:
  418.  *    A return status.
  419.  *
  420.  * Side effects:
  421.  *    The write to the remote file.
  422.  *
  423.  *----------------------------------------------------------------------
  424.  */
  425.  
  426. ReturnStatus
  427. Fsrmt_Write(streamPtr, writePtr, waitPtr, replyPtr)
  428.     Fs_Stream        *streamPtr;    /* Open stream to a remote thing */
  429.     Fs_IOParam        *writePtr;    /* Read parameter block */
  430.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  431.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  432. {
  433.     register Fsrmt_IOHandle *rmtHandlePtr =
  434.         (Fsrmt_IOHandle *)streamPtr->ioHandlePtr;
  435.     ReturnStatus     status = SUCCESS;
  436.     Rpc_Storage     storage;
  437.     FsrmtIOParam    writeParams;
  438.     int            amountWritten;    /* Total amount written */
  439.     register int    writeLen;    /* Amount to write each RPC */
  440.     register Boolean    userSpace = writePtr->flags & FS_USER;
  441.     register Address    writeBufferPtr = (Address) NIL;
  442.  
  443.     /*
  444.      * Initialize things that won't change on each RPC.
  445.      */
  446.     writeParams.fileID = rmtHandlePtr->hdr.fileID;
  447.     writeParams.streamID = streamPtr->hdr.fileID;
  448.     if (waitPtr == (Sync_RemoteWaiter *)NIL) {
  449.     writeParams.waiter.hostID = -1;
  450.     writeParams.waiter.pid = -1;
  451.     } else {
  452.     writeParams.waiter = *waitPtr;
  453.     }
  454.  
  455.     writeParams.io.buffer = 0;    /* not used */
  456.     writeParams.io.flags = writePtr->flags & ~FS_USER;
  457.     writeParams.io.procID = writePtr->procID;
  458.     writeParams.io.familyID = writePtr->familyID;
  459.     writeParams.io.uid = writePtr->uid;
  460.     writeParams.io.reserved = 0;
  461.  
  462.     storage.requestParamPtr = (Address)&writeParams;
  463.     storage.requestParamSize = sizeof(writeParams);
  464.     storage.replyParamPtr = (Address) replyPtr;
  465.     storage.replyParamSize = sizeof(Fs_IOReply);
  466.     storage.replyDataPtr = (Address)NIL;
  467.     storage.replyDataSize = 0;
  468.  
  469.     if (userSpace) {
  470.     /*
  471.      * We suffer a malloc and copy cost here because we don't
  472.      * map the users buffer into the kernel and we can't rely
  473.      * on being able to address the users context from the
  474.      * interrupt handler that receives the packet.
  475.      */
  476.     writeBufferPtr = (Address)malloc((writePtr->length > fsMaxRpcDataSize) ?
  477.                      fsMaxRpcDataSize : writePtr->length);
  478.     }
  479.     /*
  480.      * Outer loop to chop reads into the largest pieces
  481.      * supported by the RPC system.
  482.      */
  483.     amountWritten = 0;
  484.     while (writePtr->length > 0) {
  485.     writeLen = (writePtr->length > fsMaxRpcDataSize) ?
  486.             fsMaxRpcDataSize : writePtr->length;
  487.     if (userSpace) {
  488.         if (Vm_CopyIn(writeLen, writePtr->buffer + amountWritten,
  489.             writeBufferPtr) != SUCCESS) {
  490.         status = FS_INVALID_ARG;
  491.         break;
  492.         }
  493.     } else {
  494.         writeBufferPtr = writePtr->buffer + amountWritten;
  495.     }
  496.     storage.requestDataPtr = writeBufferPtr;
  497.     storage.requestDataSize = writeLen;
  498.     writeParams.io.offset = writePtr->offset + amountWritten;
  499.     writeParams.io.length = writeLen;
  500.     
  501.     status = Rpc_Call(rmtHandlePtr->hdr.fileID.serverID, RPC_FS_WRITE,
  502.             &storage);
  503.     if (status == SUCCESS || status == FS_WOULD_BLOCK) {
  504.         writePtr->length -= replyPtr->length;
  505.         amountWritten += replyPtr->length;
  506.         if (status == FS_WOULD_BLOCK || replyPtr->length < writeLen) {
  507.         break;
  508.         }
  509.     } else if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  510.         status == RPC_SERVICE_DISABLED) {
  511.         Fsutil_WantRecovery((Fs_HandleHeader *)rmtHandlePtr);
  512.         break;
  513.     } else {
  514.         break;
  515.     }
  516.     }
  517.     replyPtr->length = amountWritten;
  518.     Fs_StatAdd(amountWritten, fs_Stats.gen.remoteBytesWritten,
  519.            fs_Stats.gen.remoteWriteOverflow);
  520. #ifdef SOSP91
  521.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  522.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  523.         (proc_RunningProcesses[0]->genFlags &
  524.         (PROC_FOREIGN | PROC_MIGRATING))) {
  525.         Fs_StatAdd(amountWritten, fs_SospMigStats.gen.remoteBytesWritten, 
  526.             fs_SospMigStats.gen.remoteWriteOverflow);
  527.     }
  528.     }
  529. #endif SOSP91
  530.     if (userSpace) {
  531.     free(writeBufferPtr);
  532.     }
  533.     return(status);
  534. }
  535.  
  536. /*
  537.  *----------------------------------------------------------------------
  538.  *
  539.  * Fsrmt_RpcWrite --
  540.  *
  541.  *    Server stub for the FS_RPC_WRITE call.  This verifies the client
  542.  *    and then calls the stream-type write routine.
  543.  *
  544.  * Results:
  545.  *    If this procedure returns SUCCESS then a reply has been sent to the
  546.  *    client.  If the arguments are bad then FS_STALE_HANDLE is returned
  547.  *    and the main level sends back an error reply.
  548.  *
  549.  * Side effects:
  550.  *    The write on the stream.  See also the stream write routines.
  551.  *
  552.  *----------------------------------------------------------------------
  553.  */
  554. /*ARGSUSED*/
  555. ReturnStatus
  556. Fsrmt_RpcWrite(srvToken, clientID, command, storagePtr)
  557.     ClientData          srvToken;    /* Handle on server process passed to
  558.                      * Rpc_Reply */
  559.     int          clientID;    /* Sprite ID of client host */
  560.     int          command;    /* IGNORED */
  561.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  562.                      * request buffers and also indicate 
  563.                      * the exact amount of data in the 
  564.                      * request buffers.  The reply fields 
  565.                      * are initialized to NIL for the
  566.                       * pointers and 0 for the lengths.  
  567.                      * This can be passed to Rpc_Reply */
  568. {
  569.     register Fs_HandleHeader     *hdrPtr;
  570.     register FsrmtIOParam    *paramsPtr;
  571.     register Fs_Stream        *streamPtr;
  572.     Fs_Stream            dummyStream;
  573.     Fs_IOReply            *replyPtr;
  574.     ReturnStatus         status;
  575.     Rpc_ReplyMem        *replyMemPtr;
  576.  
  577.     paramsPtr = (FsrmtIOParam *) storagePtr->requestParamPtr;
  578.  
  579.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  580.         (¶msPtr->fileID, clientID, (int *)NIL);
  581.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  582.     printf( "Fsrmt_RpcWrite, stale handle <%d,%d> client %d\n",
  583.         paramsPtr->fileID.major, paramsPtr->fileID.minor, clientID);
  584.     return(FS_STALE_HANDLE);
  585.     }
  586.     Fsutil_HandleUnlock(hdrPtr);
  587.  
  588.     replyPtr = mnew(Fs_IOReply);
  589.     replyPtr->length = 0;
  590.     replyPtr->flags = 0;
  591.     replyPtr->signal = 0;
  592.  
  593.     paramsPtr->io.flags &= ~FS_USER;
  594.     if (paramsPtr->io.flags & FS_CLIENT_CACHE_WRITE) {
  595.     dummyStream.ioHandlePtr = hdrPtr;
  596.     streamPtr = &dummyStream;
  597.     } else {
  598.     streamPtr = Fsio_StreamClientVerify(¶msPtr->streamID, hdrPtr,
  599.             clientID);
  600.     if (streamPtr == (Fs_Stream *)NIL) {
  601.         printf("Fsrmt_RpcWrite no stream <%d> to handle <%d,%d> client %d\n",
  602.             paramsPtr->streamID.minor,
  603.             paramsPtr->fileID.major, paramsPtr->fileID.minor,
  604.             clientID);
  605.         status = (paramsPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  606.                              : FS_STALE_HANDLE;
  607.         goto exit;
  608.     } else {
  609.         if (paramsPtr->io.flags & FS_RMT_SHARED) {
  610.         paramsPtr->io.offset = streamPtr->offset;
  611.         }
  612.         Fsutil_HandleUnlock(streamPtr);
  613.     }
  614.     }
  615. #ifdef SOSP91
  616.     paramsPtr->io.reserved = clientID;
  617. #endif SOSP91
  618.     FSUTIL_TRACE_IO(FSUTIL_TRACE_SRV_WRITE_2, hdrPtr->fileID,
  619.         paramsPtr->io.offset, paramsPtr->io.length );
  620.     paramsPtr->io.buffer = storagePtr->requestDataPtr;
  621.     status = (fsio_StreamOpTable[hdrPtr->fileID.type].write)(streamPtr,
  622.         ¶msPtr->io, ¶msPtr->waiter, replyPtr);
  623.     if (streamPtr != &dummyStream) {
  624.     streamPtr->offset = paramsPtr->io.offset + replyPtr->length;
  625.     Fsutil_HandleLock(streamPtr);
  626.     Fsutil_HandleRelease(streamPtr, TRUE);
  627.     }
  628. exit:
  629.     Fsutil_HandleRelease(hdrPtr, FALSE);
  630.  
  631.     storagePtr->replyParamPtr = (Address)replyPtr;
  632.     storagePtr->replyParamSize = sizeof(Fs_IOReply);
  633.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  634.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  635.     replyMemPtr->dataPtr = (Address) NIL;
  636.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  637.         (ClientData)replyMemPtr);
  638.  
  639.     return(SUCCESS);
  640. }
  641.  
  642. /*
  643.  * Parameters for the file select RPC.
  644.  */
  645.  
  646. typedef struct FsRemoteSelectParams {
  647.     Fs_FileID    fileID;        /* File to be re-opened */
  648.     int        read;        /* 1 or zero */
  649.     int        write;        /* 1 or zero */
  650.     int        except;        /* 1 or zero */
  651.     Sync_RemoteWaiter waiter;    /* Process info for remote waiting */
  652. } FsRemoteSelectParams;
  653.  
  654. typedef struct FsRemoteSelectResults {
  655.     int        read;        /* 1 or zero */
  656.     int        write;        /* 1 or zero */
  657.     int        except;        /* 1 or zero */
  658. } FsRemoteSelectResults;
  659.  
  660. /*
  661.  *----------------------------------------------------------------------
  662.  *
  663.  * Fsrmt_Select --
  664.  *
  665.  *    Select on a remote file/device/pipe.  This does an RPC to the
  666.  *    I/O server which invokes a stream-specific select routine.
  667.  *
  668.  * Results:
  669.  *    A return status.
  670.  *
  671.  * Side effects:
  672.  *    None.
  673.  *
  674.  *----------------------------------------------------------------------
  675.  */
  676. ReturnStatus
  677. Fsrmt_Select(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  678.     Fs_HandleHeader    *hdrPtr;    /* Handle from stream to select */
  679.     Sync_RemoteWaiter    *waitPtr;    /* Information for remote waiting. */
  680.     int              *readPtr;    /* In/Out read ability */
  681.     int              *writePtr;    /* In/Out write ability */
  682.     int              *exceptPtr;    /* In/Out exception ability */
  683. {
  684.     ReturnStatus         status;
  685.     Rpc_Storage         storage;
  686.     FsRemoteSelectParams    selectParams;
  687.     FsRemoteSelectResults    selectResults;
  688.  
  689.     FSRMT_RPC_DEBUG_PRINT("Fsrmt_Select: Selecting file\n");
  690.  
  691.     selectParams.fileID = hdrPtr->fileID;
  692.     selectParams.read = *readPtr;
  693.     selectParams.write = *writePtr;
  694.     selectParams.except = *exceptPtr;
  695.     if (waitPtr == (Sync_RemoteWaiter *)NIL) {
  696.     /*
  697.      * Indicate a polling select with a NIL hostID.
  698.      */
  699.     selectParams.waiter.hostID = NIL;
  700.     } else {
  701.     selectParams.waiter = *waitPtr;
  702.     }
  703.  
  704.     storage.requestParamPtr = (Address)&selectParams;
  705.     storage.requestParamSize = sizeof(selectParams);
  706.     storage.requestDataPtr = (Address)NIL;
  707.     storage.requestDataSize = 0;
  708.  
  709.     storage.replyParamPtr = (Address) &selectResults;
  710.     storage.replyParamSize = sizeof(FsRemoteSelectResults);
  711.     storage.replyDataPtr = (Address) NIL;
  712.     storage.replyDataSize = 0;
  713.  
  714.     status = Rpc_Call(hdrPtr->fileID.serverID, RPC_FS_SELECT, &storage);
  715.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  716.     status == RPC_SERVICE_DISABLED) {
  717.     /*
  718.      * Mask the error and leave the bits set in the request masks.
  719.      * This will cause the application to try a read or write
  720.      * of this stream and then it will learn something is amiss.
  721.      */
  722.     Fsutil_WantRecovery(hdrPtr);
  723.     status = SUCCESS;
  724.     } else {
  725.     *readPtr = selectResults.read;
  726.     *writePtr = selectResults.write;
  727.     *exceptPtr = selectResults.except;
  728.     }
  729.  
  730.     return(status);
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * Fsrmt_RpcSelectStub --
  737.  *
  738.  *    The service stub for RPC_FS_SELECT.
  739.  *
  740.  * Results:
  741.  *    If this procedure returns SUCCESS then a reply has been sent to
  742.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  743.  *    returned and the main level sends back an error reply.
  744.  *
  745.  * Side effects:
  746.  *    Calls the domain-level select routine to attempt the lock operation.
  747.  *
  748.  *----------------------------------------------------------------------
  749.  */
  750. /*ARGSUSED*/
  751. ReturnStatus
  752. Fsrmt_RpcSelectStub(srvToken, clientID, command, storagePtr)
  753.     ClientData srvToken;    /* Handle on server process passed to
  754.                  * Rpc_Reply */
  755.     int clientID;        /* Sprite ID of client host */
  756.     int command;        /* Command identifier */
  757.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  758.                  * buffers and also indicate the exact amount
  759.                  * of data in the request buffers.  The reply
  760.                  * fields are initialized to NIL for the
  761.                  * pointers and 0 for the lengths.  This can
  762.                  * be passed to Rpc_Reply */
  763. {
  764.     register    FsRemoteSelectParams    *paramsPtr;
  765.     register    FsRemoteSelectResults    *resultsPtr;
  766.     register    Fs_HandleHeader        *hdrPtr;
  767.     register    Rpc_ReplyMem        *replyMemPtr;
  768.     register    Sync_RemoteWaiter    *waitPtr;
  769.     ReturnStatus            status;
  770.  
  771.     FSRMT_RPC_DEBUG_PRINT("RPC select request\n");
  772.  
  773.     paramsPtr = (FsRemoteSelectParams *)storagePtr->requestParamPtr;
  774.  
  775.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  776.     (¶msPtr->fileID, clientID, (int *)NIL);
  777.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  778.     return(FS_STALE_HANDLE);
  779.     }
  780.     Fsutil_HandleUnlock(hdrPtr);
  781.     if (paramsPtr->waiter.hostID == NIL) {
  782.     /*
  783.      * Indicate a polling select.
  784.      */
  785.     waitPtr = (Sync_RemoteWaiter *)NIL;
  786.     } else {
  787.     waitPtr = ¶msPtr->waiter;
  788.     }
  789.     status = (*fsio_StreamOpTable[paramsPtr->fileID.type].select)
  790.     (hdrPtr, waitPtr, ¶msPtr->read,
  791.      ¶msPtr->write, ¶msPtr->except);
  792.     Fsutil_HandleRelease(hdrPtr, FALSE);
  793.     if (status == SUCCESS) {
  794.     resultsPtr = mnew(FsRemoteSelectResults);
  795.     resultsPtr->read = paramsPtr->read;
  796.     resultsPtr->write = paramsPtr->write;
  797.     resultsPtr->except = paramsPtr->except;
  798.     storagePtr->replyParamPtr = (Address) resultsPtr;
  799.     storagePtr->replyParamSize = sizeof(FsRemoteSelectResults);
  800.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  801.     replyMemPtr->paramPtr = (Address) resultsPtr;
  802.     replyMemPtr->dataPtr = (Address) NIL;
  803.     Rpc_Reply(srvToken, SUCCESS, storagePtr, 
  804.           (int (*)()) Rpc_FreeMem, (ClientData) replyMemPtr);
  805.     } else {
  806.     Rpc_Reply(srvToken, status, storagePtr, 
  807.           (int (*)())NIL, (ClientData)NIL);
  808.     }
  809.  
  810.     return(SUCCESS);
  811. }
  812.  
  813. /*
  814.  *----------------------------------------------------------------------
  815.  *
  816.  * Fsrmt_IOControl --
  817.  *
  818.  *    Client stub for RPC_FS_IOCONTROL.
  819.  *    Do a special operation on a remote Sprite file/device/pipe/etc.
  820.  *
  821.  * Results:
  822.  *    None.
  823.  *
  824.  * Side effects:
  825.  *    None.
  826.  *
  827.  *----------------------------------------------------------------------
  828.  */
  829. ReturnStatus
  830. Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr)
  831.     Fs_Stream    *streamPtr;
  832.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  833.     Fs_IOReply *replyPtr;        /* Return length and signal */
  834. {
  835.     register Fs_HandleHeader    *hdrPtr = streamPtr->ioHandlePtr;
  836.     FsrmtIOCParam        params;
  837.     ReturnStatus        status;
  838.     Rpc_Storage            storage;
  839.  
  840.     FSRMT_RPC_DEBUG_PRINT("Fsrmt_IOControl\n");
  841.  
  842.     params.fileID = hdrPtr->fileID;
  843.     params.streamID = streamPtr->hdr.fileID;
  844.     params.procID = ioctlPtr->procID;
  845.     params.familyID = ioctlPtr->familyID;
  846.     params.command = ioctlPtr->command;
  847.     params.inBufSize = ioctlPtr->inBufSize;
  848.     params.outBufSize = ioctlPtr->outBufSize;
  849.     params.format = ioctlPtr->format;
  850.     params.uid = ioctlPtr->uid;
  851.  
  852.     storage.requestParamPtr = (Address)¶ms;
  853.     storage.requestParamSize = sizeof(FsrmtIOCParam);
  854.     storage.requestDataPtr = (Address) ioctlPtr->inBuffer;
  855.     storage.requestDataSize = ioctlPtr->inBufSize;
  856.     storage.replyParamPtr = (Address)replyPtr;
  857.     storage.replyParamSize = sizeof(Fs_IOReply);
  858.     storage.replyDataPtr = (Address)ioctlPtr->outBuffer;
  859.     storage.replyDataSize = ioctlPtr->outBufSize;
  860.  
  861.     status = Rpc_Call(hdrPtr->fileID.serverID, RPC_FS_IO_CONTROL, &storage);
  862.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  863.     status == RPC_SERVICE_DISABLED) {
  864.     Fsutil_WantRecovery(hdrPtr);
  865.     }
  866.  
  867.     return(status);
  868. }
  869.  
  870. /*
  871.  *----------------------------------------------------------------------
  872.  *
  873.  * Fsrmt_RpcIOControl --
  874.  *
  875.  *    Service stub for RPC_FS_IOCONTROL.
  876.  *
  877.  * Results:
  878.  *    If this procedure returns SUCCESS then a reply has been sent to
  879.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  880.  *    returned and the main level sends back an error reply.
  881.  *
  882.  * Side effects:
  883.  *    Calls the local io control routine.
  884.  *
  885.  *----------------------------------------------------------------------
  886.  */
  887. /*ARGSUSED*/
  888. ReturnStatus
  889. Fsrmt_RpcIOControl(srvToken, clientID, command, storagePtr)
  890.     ClientData srvToken;    /* Handle on server process passed to
  891.                  * Rpc_Reply */
  892.     int clientID;        /* Sprite ID of client host */
  893.     int command;        /* IGNORED */
  894.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  895.                  * buffers and also indicate the exact amount
  896.                  * of data in the request buffers.  The reply
  897.                  * fields are initialized to NIL for the
  898.                  * pointers and 0 for the lengths.  This can
  899.                  * be passed to Rpc_Reply */
  900. {
  901.     register    FsrmtIOCParam    *paramsPtr;
  902.     register    Fs_HandleHeader        *hdrPtr;
  903.     register    Fs_Stream        *streamPtr;
  904.     register    Rpc_ReplyMem        *replyMemPtr;
  905.     ReturnStatus            status = SUCCESS;
  906.     Address                outBufPtr;
  907.     Fs_IOCParam                ioctl;
  908.     Fs_IOReply                *replyPtr;
  909.  
  910.     paramsPtr = (FsrmtIOCParam *)storagePtr->requestParamPtr;
  911.  
  912.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  913.         (¶msPtr->fileID, clientID, (int *)NIL);
  914.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  915.     printf("Fsrmt_RpcIOControl, no handle <%d,%d> client %d\n",
  916.         paramsPtr->fileID.major, paramsPtr->fileID.minor, clientID);
  917.     return(FS_STALE_HANDLE);
  918.     }
  919.     streamPtr = Fsio_StreamClientVerify(¶msPtr->streamID, hdrPtr, clientID);
  920.     if (streamPtr == (Fs_Stream *)NIL) {
  921.     printf("Fsrmt_RpcIOControl no stream <%d> to handle <%d,%d> client %d\n",
  922.         paramsPtr->streamID.minor,
  923.         paramsPtr->fileID.major, paramsPtr->fileID.minor,
  924.         clientID);
  925.     Fsutil_HandleRelease(hdrPtr, TRUE);
  926.     return( (paramsPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  927.                         : FS_STALE_HANDLE );
  928.     }
  929.     Fsutil_HandleUnlock(hdrPtr);
  930.  
  931.     if (paramsPtr->outBufSize != 0) {
  932.     outBufPtr = (Address)malloc(paramsPtr->outBufSize);
  933.     } else {
  934.     outBufPtr = (Address)NIL;
  935.     }
  936.     ioctl.command = paramsPtr->command;
  937.     ioctl.inBuffer = storagePtr->requestDataPtr;
  938.     ioctl.inBufSize = paramsPtr->inBufSize;
  939.     ioctl.outBuffer = outBufPtr;
  940.     ioctl.outBufSize = paramsPtr->outBufSize;
  941.     ioctl.flags = 0;    /* All buffers in kernel space */
  942.     ioctl.format = paramsPtr->format;
  943.     ioctl.procID = paramsPtr->procID;
  944.     ioctl.familyID = paramsPtr->familyID;
  945.     ioctl.uid = paramsPtr->uid;
  946.  
  947.     replyPtr = mnew(Fs_IOReply);
  948.     replyPtr->length = paramsPtr->outBufSize;
  949.     replyPtr->flags = 0;
  950.     replyPtr->signal = 0;
  951.     replyPtr->code = 0;
  952.  
  953.     /*
  954.      * Update server's shadow stream offset for IOC_REPOSITION
  955.      */
  956.     if (ioctl.command == IOC_REPOSITION) {
  957.     int newOffset = -1;
  958.     register Ioc_RepositionArgs *iocArgsPtr = (Ioc_RepositionArgs *) NIL;
  959.     Ioc_RepositionArgs    iocArgs;
  960.     int size;
  961.     int inSize;
  962.     int oldOffset = -1;
  963. #ifdef SOSP91
  964.     int flags = -1;
  965. #endif
  966.  
  967.     if ((ioctl.inBuffer == (Address)NIL) || 
  968.         (ioctl.inBufSize < sizeof(Ioc_RepositionArgs))) {
  969.         status = GEN_INVALID_ARG;
  970.     } else if (ioctl.format != mach_Format) {
  971.         int fmtStatus;
  972.         size = sizeof(Ioc_RepositionArgs);
  973.         inSize = ioctl.inBufSize;
  974.         fmtStatus = Fmt_Convert("ww", ioctl.format, &inSize,
  975.                 ioctl.inBuffer, mach_Format, &size,
  976.                 (Address) &iocArgs);
  977.         if (fmtStatus != 0) {
  978.         printf("Format of ioctl failed <0x%x>\n", fmtStatus);
  979.         status = GEN_INVALID_ARG;
  980.         }
  981.         if (size != sizeof(Ioc_RepositionArgs)) {
  982.         status = GEN_INVALID_ARG;
  983.         }
  984. #ifdef SOSP91
  985.         /*
  986.          * SOSP91
  987.          *
  988.          *    The old offset is included in the RPC following the
  989.          *    Ioc_RepositionArgs. If its not there assume the
  990.          *    RPC came from a client running a standard kernel.
  991.          */
  992.         if (ioctl.inBufSize == sizeof(Ioc_RepositionArgs) + 12) {
  993.         char    *offsetPtr;
  994.         int    tmp[3];
  995.         offsetPtr = ioctl.inBuffer + inSize;
  996.         inSize = 3 * sizeof(int);
  997.         size = 3 * sizeof(int);
  998.         fmtStatus = Fmt_Convert("w3", ioctl.format, &inSize,
  999.                 offsetPtr, mach_Format, &size,
  1000.                 (Address) tmp);
  1001.         if (fmtStatus != 0) {
  1002.             printf("Format of old offset failed <0x%x>\n", 
  1003.             fmtStatus);
  1004.         }
  1005.         if (size != 3 * sizeof(int)) {
  1006.             printf("Old offset wrong size %d\n", size);
  1007.         }
  1008.         oldOffset = tmp[0];
  1009.         size = tmp[1];
  1010.         flags = tmp[2];
  1011.         } else {
  1012. #else
  1013.         {
  1014. #endif
  1015.         oldOffset = streamPtr->offset;
  1016.         }
  1017.         iocArgsPtr = &iocArgs;
  1018.     } else {
  1019.         iocArgsPtr = (Ioc_RepositionArgs *)ioctl.inBuffer;
  1020. #ifdef SOSP91
  1021.         if (ioctl.inBufSize == sizeof(Ioc_RepositionArgs) + 12) {
  1022.         int *ptr = (int *)(ioctl.inBuffer + sizeof(Ioc_RepositionArgs));
  1023.         oldOffset = *ptr++;
  1024.         size = *ptr++;
  1025.         flags = *ptr;
  1026.         } else {
  1027.         oldOffset = streamPtr->offset;
  1028.         }
  1029. #endif
  1030.     }
  1031. #ifdef SOSP91
  1032.     if (streamPtr->flags & FS_RMT_SHARED) {
  1033.         oldOffset = streamPtr->offset;
  1034.     }
  1035. #endif
  1036.     if (status == SUCCESS) {
  1037.         switch(iocArgsPtr->base) {
  1038.         case IOC_BASE_ZERO:
  1039.             newOffset = iocArgsPtr->offset;
  1040.             break;
  1041.         case IOC_BASE_CURRENT:
  1042.             newOffset = oldOffset + iocArgsPtr->offset;
  1043.             break;
  1044.         case IOC_BASE_EOF: {
  1045.             Fs_Attributes attrs;
  1046.     
  1047.             status = Fs_GetAttrStream(streamPtr, &attrs);
  1048.             if (status != SUCCESS) {
  1049.             break;
  1050.             }
  1051.             if (streamPtr->nameInfoPtr != (Fs_NameInfo *) NIL) {
  1052.             size = attrs.size;
  1053.             }
  1054.             newOffset = size + iocArgsPtr->offset;
  1055.             break;
  1056.         }
  1057.         }
  1058.         if (newOffset < 0) {
  1059.         status = GEN_INVALID_ARG;
  1060.         } else {
  1061.         if (ioctl.outBufSize >= sizeof(int) &&
  1062.             ioctl.outBuffer == (Address) NIL) {
  1063.             if (ioctl.format != mach_Format) {
  1064.             int size = sizeof(int);
  1065.             int inSize = sizeof(int);
  1066.             int fmtStatus;
  1067.             fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1068.                         (Address) &newOffset,
  1069.                         ioctl.format, 
  1070.                         &size,
  1071.                         (Address) ioctl.outBuffer);
  1072.             if (fmtStatus != 0) {
  1073.                 printf("Format of ioctl failed <0x%x>\n",
  1074.                    fmtStatus);
  1075.                 status = GEN_INVALID_ARG;
  1076.             }
  1077.             if (size != sizeof(int)) {
  1078.                 status = GEN_INVALID_ARG;
  1079.             }
  1080.             } else {
  1081.             *(int *)ioctl.outBuffer = newOffset;
  1082.             }
  1083.         }
  1084.         if (status == SUCCESS) {
  1085. #ifdef SOSP91
  1086.             if (oldOffset != newOffset) {
  1087.             SOSP_ADD_LSEEK_TRACE(streamPtr->hdr.fileID, oldOffset,
  1088.                 newOffset, flags);
  1089.             }
  1090. #endif
  1091.             streamPtr->offset = newOffset;
  1092.         }
  1093.         }
  1094.     }
  1095.     }
  1096.     Fsutil_HandleRelease(streamPtr, TRUE);
  1097.     if (status == SUCCESS) {
  1098.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].ioControl)(streamPtr,
  1099.             &ioctl, replyPtr);
  1100. #ifdef lint
  1101.     status = Fsio_FileIOControl(streamPtr, &ioctl, replyPtr);
  1102.     status = Fsio_PipeIOControl(streamPtr, &ioctl, replyPtr);
  1103.     status = Fsio_DeviceIOControl(streamPtr, &ioctl, replyPtr);
  1104.     status = FspdevPseudoStreamIOControl(streamPtr, &ioctl, replyPtr);
  1105. #endif /* lint */
  1106.     }
  1107.     Fsutil_HandleRelease(hdrPtr, FALSE);
  1108.  
  1109.     FSRMT_RPC_DEBUG_PRINT1("Fsrmt_RpcIOControl returns <%x>\n", status);
  1110.  
  1111.     if ((replyPtr->length == 0) && (outBufPtr != (Address)NIL)) {
  1112.     free((Address) outBufPtr);
  1113.     outBufPtr = (Address)NIL;
  1114.     }
  1115.     storagePtr->replyDataPtr = outBufPtr;
  1116.     storagePtr->replyDataSize = replyPtr->length;
  1117.     storagePtr->replyParamPtr = (Address)replyPtr;
  1118.     storagePtr->replyParamSize = sizeof(Fs_IOReply);
  1119.  
  1120.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1121.     replyMemPtr->paramPtr = (Address)replyPtr;
  1122.     replyMemPtr->dataPtr = outBufPtr;
  1123.     Rpc_Reply(srvToken, status, storagePtr, 
  1124.           (int (*)()) Rpc_FreeMem, (ClientData) replyMemPtr);
  1125.  
  1126.     return(SUCCESS);
  1127. }
  1128.  
  1129. /*
  1130.  *----------------------------------------------------------------------
  1131.  *
  1132.  * Fsrmt_BlockCopy --
  1133.  *
  1134.  *    Copy the file system block from the source to the destination file.
  1135.  *    This only works for remote file handles as this is only used
  1136.  *    on remote swap files.
  1137.  *
  1138.  * Results:
  1139.  *    Return status from the rpc to the server.
  1140.  *
  1141.  * Side effects:
  1142.  *    The RPC does the block copy on the server.
  1143.  *
  1144.  *----------------------------------------------------------------------
  1145.  */
  1146.  
  1147. ReturnStatus
  1148. Fsrmt_BlockCopy(srcHdrPtr, dstHdrPtr, blockNum)
  1149.     Fs_HandleHeader    *srcHdrPtr;    /* Source file handle. */
  1150.     Fs_HandleHeader    *dstHdrPtr;    /* Dest file handle. */
  1151.     int            blockNum;    /* Block to copy. */
  1152. {
  1153.     ReturnStatus         status;
  1154.     FsrmtBlockCopyParam    params;
  1155.     Rpc_Storage         storage;
  1156.     Fsrmt_FileIOHandle        *srcHandlePtr;
  1157.     Fsrmt_FileIOHandle        *dstHandlePtr;
  1158.  
  1159.     if (srcHdrPtr->fileID.type != FSIO_RMT_FILE_STREAM) {
  1160.     panic( "Fsrmt_BlockCopy, bad stream type <%d>\n",
  1161.         srcHdrPtr->fileID.type);
  1162.     srcHandlePtr = (Fsrmt_FileIOHandle *) NIL;
  1163.     dstHandlePtr = (Fsrmt_FileIOHandle *) NIL;
  1164.     return(FAILURE);
  1165.     } else {
  1166.     srcHandlePtr = (Fsrmt_FileIOHandle *)srcHdrPtr;
  1167.     dstHandlePtr = (Fsrmt_FileIOHandle *)dstHdrPtr;
  1168.     }
  1169.  
  1170.     params.srcFileID = srcHdrPtr->fileID;
  1171.     params.destFileID = dstHdrPtr->fileID;
  1172.     params.blockNum = blockNum;
  1173.     storage.requestParamPtr = (Address)¶ms;
  1174.     storage.requestParamSize = sizeof(FsrmtBlockCopyParam);
  1175.     storage.requestDataPtr = (Address)NIL;
  1176.     storage.requestDataSize = 0;
  1177.     storage.replyParamPtr = (Address)NIL;
  1178.     storage.replyParamSize = 0;
  1179.     storage.replyDataPtr = (Address)NIL;
  1180.     storage.replyDataSize = 0;
  1181.  
  1182.     status = Rpc_Call(srcHdrPtr->fileID.serverID, RPC_FS_COPY_BLOCK, &storage);
  1183.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  1184.     status == RPC_SERVICE_DISABLED) {
  1185.     Fsutil_WantRecovery((Fs_HandleHeader *)srcHandlePtr);
  1186.     Fsutil_WantRecovery((Fs_HandleHeader *)dstHandlePtr);
  1187.     }
  1188.     return(status);
  1189. }
  1190.  
  1191.  
  1192. /*
  1193.  *----------------------------------------------------------------------
  1194.  *
  1195.  * Fsrmt_RpcBlockCopy --
  1196.  *
  1197.  *    Service stub for Fsrmt_BlockCopy.
  1198.  *
  1199.  * Results:
  1200.  *    If this procedure returns SUCCESS then a reply has been sent to
  1201.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  1202.  *    returned and the main level sends back an error reply.
  1203.  *
  1204.  * Side effects:
  1205.  *    Calls the local io control routine.
  1206.  *
  1207.  *----------------------------------------------------------------------
  1208.  */
  1209. /*ARGSUSED*/
  1210. ReturnStatus
  1211. Fsrmt_RpcBlockCopy(srvToken, clientID, command, storagePtr)
  1212.     ClientData srvToken;    /* Handle on server process passed to
  1213.                  * Rpc_Reply */
  1214.     int clientID;        /* Sprite ID of client host */
  1215.     int command;        /* IGNORED */
  1216.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1217.                  * buffers and also indicate the exact amount
  1218.                  * of data in the request buffers.  The reply
  1219.                  * fields are initialized to NIL for the
  1220.                  * pointers and 0 for the lengths.  This can
  1221.                  * be passed to Rpc_Reply */
  1222. {
  1223.     register    FsrmtBlockCopyParam    *paramsPtr;
  1224.     register    Fs_HandleHeader        *srcHdrPtr;
  1225.     register    Fs_HandleHeader        *dstHdrPtr;
  1226.     ReturnStatus            status;
  1227.  
  1228.     FSRMT_RPC_DEBUG_PRINT("RPC block copy request\n");
  1229.  
  1230.     paramsPtr = (FsrmtBlockCopyParam *)storagePtr->requestParamPtr;
  1231.  
  1232.     /*
  1233.      * Fetch the source and dest handles.  We know that they won't go away
  1234.      * while we are using them because of the way swap files are handled.
  1235.      */
  1236.     dstHdrPtr = (*fsio_StreamOpTable[paramsPtr->destFileID.type].clientVerify)
  1237.         (¶msPtr->destFileID, clientID, (int *)NIL);
  1238.     if (dstHdrPtr == (Fs_HandleHeader *)NIL) {
  1239.     return(FS_STALE_HANDLE);
  1240.     }
  1241.     Fsutil_HandleRelease(dstHdrPtr, TRUE);
  1242.  
  1243.     srcHdrPtr = (*fsio_StreamOpTable[paramsPtr->srcFileID.type].clientVerify)
  1244.         (¶msPtr->srcFileID, clientID, (int *)NIL);
  1245.     if (srcHdrPtr == (Fs_HandleHeader *)NIL) {
  1246.     return(FS_STALE_HANDLE);
  1247.     }
  1248.  
  1249.     status = (*fsio_StreamOpTable[paramsPtr->srcFileID.type].blockCopy)
  1250.                 (srcHdrPtr, dstHdrPtr, paramsPtr->blockNum);
  1251.     Fsutil_HandleRelease(srcHdrPtr, TRUE);
  1252.  
  1253.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  1254.     return(SUCCESS);
  1255. }
  1256.  
  1257. /*
  1258.  * The return values from the RPC_FS_DOMAIN_INFO call.
  1259.  * (The inputs are a fileID.)
  1260.  */
  1261. typedef struct FsDomainInfoResults {
  1262.     Fs_DomainInfo    domain;
  1263.     Fs_FileID        fileID;
  1264. } FsDomainInfoResults;
  1265. /*
  1266.  *----------------------------------------------------------------------
  1267.  *
  1268.  * Fsrmt_DomainInfo --
  1269.  *
  1270.  *    Return information about the given domain.
  1271.  *
  1272.  * Results:
  1273.  *    None.
  1274.  *
  1275.  * Side effects:
  1276.  *    None.
  1277.  *
  1278.  *----------------------------------------------------------------------
  1279.  */
  1280. ReturnStatus
  1281. Fsrmt_DomainInfo(fileIDPtr, domainInfoPtr)
  1282.     Fs_FileID        *fileIDPtr;
  1283.     Fs_DomainInfo    *domainInfoPtr;    
  1284. {
  1285.     register ReturnStatus    status;
  1286.     FsDomainInfoResults        results;
  1287.     Rpc_Storage            storage;
  1288.  
  1289. #ifdef notdef
  1290. retry:
  1291. #endif
  1292.     storage.requestParamPtr = (Address)fileIDPtr;
  1293.     storage.requestParamSize = sizeof(Fs_FileID);
  1294.     storage.requestDataPtr = (Address) NIL;
  1295.     storage.requestDataSize = 0;
  1296.     storage.replyParamPtr = (Address)&results;
  1297.     storage.replyParamSize = sizeof(FsDomainInfoResults);
  1298.     storage.replyDataPtr = (Address) NIL;
  1299.     storage.replyDataSize = 0;
  1300.  
  1301.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_DOMAIN_INFO, &storage);
  1302.  
  1303.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  1304.     status == RPC_SERVICE_DISABLED) {
  1305.     /*
  1306.      * Wait for recovery here, instead of higher up in Fsutil_DomainInfo.
  1307.      * This is because the server-side stub can't check against
  1308.      * stale handle conditions, so it always calls Fsutil_DomainInfo.
  1309.      * We don't want to ever wait for recovery on the server,
  1310.      * so we do it here where we know we are a client.
  1311.      */
  1312.     Fs_HandleHeader *hdrPtr;
  1313.     hdrPtr = Fsutil_HandleFetch(fileIDPtr);
  1314.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  1315.         printf("Fsrmt_DomainInfo: Can't fetch <%d,%d,%d,%d>\n",
  1316.             fileIDPtr->type, fileIDPtr->serverID,
  1317.             fileIDPtr->major, fileIDPtr->minor);
  1318.     } else {
  1319.         Fsutil_HandleUnlock(hdrPtr);
  1320.         Fsutil_WantRecovery(hdrPtr);
  1321. #ifdef notdef
  1322.         /*
  1323.          * We don't wait for recovery because that hangs getwd(),
  1324.          * which in turn hangs shell scripts.  We have marked the
  1325.          * handle as needing recovery, however, so recovery will
  1326.          * happen eventually.
  1327.          */
  1328.         printf("Fsrmt_DomainInfo: waiting for recovery <%d,%d> server %d\n",
  1329.             fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  1330.         status = Fsutil_WaitForRecovery(hdrPtr, status);
  1331.         if (status == SUCCESS) {
  1332.         goto retry;
  1333.         }
  1334. #endif
  1335.     }
  1336.     }
  1337.     if (status == SUCCESS) {
  1338.     *domainInfoPtr = results.domain;
  1339.     *fileIDPtr = results.fileID;
  1340.     }
  1341.  
  1342.     return(status);
  1343. }
  1344.  
  1345. /*
  1346.  *----------------------------------------------------------------------
  1347.  *
  1348.  * Fsrmt_RpcDomainInfo --
  1349.  *
  1350.  *    Service stub for RPC_FS_DOMAIN_INFO.
  1351.  *
  1352.  * Results:
  1353.  *    If this procedure returns SUCCESS then a reply has been sent to
  1354.  *    the client.  If the arguments are bad then FS_DOMAIN_UNAVAILABLE is
  1355.  *    returned and the main level sends back an error reply.
  1356.  *
  1357.  * Side effects:
  1358.  *    Calls the top-level Fsutil_DomainInfo routine to get information
  1359.  *    about the domain.
  1360.  *
  1361.  *----------------------------------------------------------------------
  1362.  */
  1363. /*ARGSUSED*/
  1364. ReturnStatus
  1365. Fsrmt_RpcDomainInfo(srvToken, clientID, command, storagePtr)
  1366.     ClientData srvToken;    /* Handle on server process passed to
  1367.                  * Rpc_Reply */
  1368.     int clientID;        /* IGNORED */
  1369.     int command;        /* IGNORED */
  1370.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1371.                  * buffers and also indicate the exact amount
  1372.                  * of data in the request buffers.  The reply
  1373.                  * fields are initialized to NIL for the
  1374.                  * pointers and 0 for the lengths.  This can
  1375.                  * be passed to Rpc_Reply */
  1376. {
  1377.     ReturnStatus    status;
  1378.     Fs_FileID        *fileIDPtr;
  1379.     FsDomainInfoResults    *resultsPtr;
  1380.     Rpc_ReplyMem    *replyMemPtr;
  1381.  
  1382.     fileIDPtr = (Fs_FileID *)storagePtr->requestParamPtr;
  1383.     resultsPtr = mnew(FsDomainInfoResults);
  1384.     fileIDPtr->type = Fsio_MapRmtToLclType(fileIDPtr->type);
  1385.     resultsPtr->fileID = *fileIDPtr;
  1386.  
  1387.     status = Fsutil_DomainInfo(&resultsPtr->fileID, &resultsPtr->domain);
  1388.  
  1389.     storagePtr->replyParamPtr = (Address) resultsPtr;
  1390.     storagePtr->replyParamSize = sizeof(FsDomainInfoResults);
  1391.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1392.     replyMemPtr->paramPtr = (Address) resultsPtr;
  1393.     replyMemPtr->dataPtr = (Address) NIL;
  1394.     Rpc_Reply(srvToken, status, storagePtr, 
  1395.           (int (*)()) Rpc_FreeMem, (ClientData) replyMemPtr);
  1396.  
  1397.     return(SUCCESS);    /* Because we've already replied */
  1398. }
  1399.